/**
 * Controller to handle requests from an account detail page to get JSON containing
 * a mapping of days over the last 90 days to the number of feed updates for the account
 * that day.
 *
 * Any questions, concerns, or suggestions, find me on Chatter Dev Zone:
 * https://na7.salesforce.com/005A0000000hIuh
 *
 * @author Ryan Ausanka-Crues
 * @version 1
 * Copyright (c) 2010 Ryan Ausanka-Crues
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the 'Software'), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * The Software shall be used for Good, not Evil.
 * 
 * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
public class HackathonSObjectController{
    /**
     * The number of days before today to include when querying for recent chatter feed updates
     */
    private final Integer dateRange = 90;
    
    /**
     * Account whose feed update graph is requested
     */
    private final SObject acct;
    
    /**
     * Constructor called because the VisualForce page is defined to have this class extend the standard
     * account controller:
     * <apex:page standardController="account" extensions="HackathonAccountController" ...
     */
    public HackathonSObjectController(ApexPages.StandardController acctController){
        // Retrieve the account from the standard controller so that we can use it later
        this.acct = acctController.getRecord();
    }
    
    /**
     * Getter called by the VisualForce page to set a hidden form field with the JSON data
     * detailing the feed updates made over the past 90 days
     */
    public String getFeedUpdateHistory() {
        SObject[] feedList = runFeedQuery(acct);
        Map<String,Integer> dateCount = collapseFeedEntries(feedList);
        // Then get the full data set to send back to the client
        JSONObject.value jsonObj = new JSONObject.Value(dateCount);
        return jsonObj.valueToString();
    }
    
    /**
     * Only here because it is required for the VisualForce page to work properly
     */
    public void setFeedUpdateHistory(String value) {}
    
    /**
     * Run the query to retrieve all recent feed updates for the given record.
     * Use the generic sObject type so that this method can be reused for all different standard
     * objects. Feed table name is dynamically constructed using the object type
     */
    public SObject[] runFeedQuery(SObject obj) {
        return Database.query('SELECT id, createdDate '+
                              'FROM '+ obj.getSObjectType().getDescribe().getName() +'Feed '+
                              'WHERE ParentId =\''+ obj.id +'\' AND createdDate >= '+ DateTime.now().addDays(-dateRange).format('yyyy-MM-dd\'T\'HH:mm:ss.SSS\'Z\'') +' '+
                              'ORDER BY Id DESC');
    }
    
    /**
     * Collapse the list of feed entries into a map of date to number of feed updates on that date
     */
    public Map<String, Integer> collapseFeedEntries(SObject[] feedData) {
        Map<String, Integer> dateCount = new Map<String, Integer>();
        // Iterate over all feed entries for the current record in the date range chosen
        for (SObject feedEntry : feedData) {
            // Format the date into a nicer format
            String dateStr = ((DateTime)feedEntry.get('createdDate')).format('yyyy-MM-dd');
            // If there were previous updates on this date, increment the existing count
            if (dateCount.get(dateStr) != null) {
                dateCount.put(dateStr, dateCount.get(dateStr) + 1);
            }
            // First update found for this date
            else {
                dateCount.put(dateStr, 1);
            }
        }
        return dateCount;
    }
}